#ifndef __MINIUTIL_FRAME_MULTINETSERVICE_H__
#define __MINIUTIL_FRAME_MULTINETSERVICE_H__

#include <list>
#include "miniutil/address.h"
#include "miniutil/buffer.h"
#include "miniutil/threadservice.h"
#include "miniutil/socketcmn.h"
#include "miniutil/socketmul_select.h"

namespace miniutil { namespace frame {
	
	class MultinetPeer
	{
		public:
			const static int STUS_IDLE = 0;
			const static int STUS_CONNECTING = 1;
			const static int STUS_CONNECTED = 2;
			const static int STUS_CONN_FAIL = 3;
			const static int STUS_CONN_BROKE = 4;
			
			const static int TYPE_ACTIVE = 0;
			const static int TYPE_PASSIVE = 1;
		public:
			miniutil::soaddr GetRemoteAddress(){return mraddr;}
			virtual int working();
			int GetNetStus(){return mstatus;}
		protected:
			MultinetPeer(miniutil::multinet::SocketMulplexService* ps,miniutil::soaddr);
			MultinetPeer(miniutil::multinet::SocketMulplexService* ps,miniutil::soaddr, SOCKET acceptsoc);
			int SendoutData(miniutil::data::shared_buffer sbuf);
			//int RetrieveData(char* buf, int len);

		protected:
			SOCKET mconnsoc;
			int mstatus;
            int mconntype;
			
			std::list<miniutil::data::shared_buffer> mtosendmsg;
			
			miniutil::soaddr mraddr;
			miniutil::mutex mtx;

			miniutil::data::fifobuf mrecvbuf;
			miniutil::multinet::SocketMulplexService* mpss;
	};
	
	//TN should be subclass of MultinetPeer
	template <class TN>
	class MultinetService:public ThreadService
	{
		public:
			MultinetService(unsigned short port)
			{
				mport = port;
				mlistensoc = NULL;
			}

			TN* GetPeer(miniutil::soaddr addr)
			{
				miniutil::auto_lock lk(&mtx);
				for(int i=0; i< (int)mvpeers.size(); i++)
					if(mvpeers[i]->GetRemoteAddress() == addr)
						return mvpeers[i];
				TN* ptn = new TN(&mss, miniutil::soaddr(addr));
				mvpeers.push_back(ptn);
				return ptn;
			}

			//MultinetPeer* AddPeer(miniutil::soaddr);
		protected:
			virtual int BeforeStart()
			{
				mss.start_service();
				if(mport != 0x00)
				{
					mlistensoc = miniutil::socketcmn::try_listen(mport, 0);
					if(mlistensoc != INVALID_SOCKET)
						mss.add_tcp_socket(mlistensoc, miniutil::multinet::EVT_INCOMING);
					else
					{
						std::cout<<"listen on port "<<mport<<"error"<<std::endl;
						mlistensoc = NULL;
					}
				}
				return 0;
			}

			//virtual int AfterStart();
			//virtual int BeforeStop();
			virtual int AfterStop()
			{
				mss.stop_service();
				if(mlistensoc != NULL)
				{
					closesocket(mlistensoc);
					mlistensoc = NULL;
				}
				for(int i=0; i< (int)mvpeers.size(); i++)
				{
					delete mvpeers[i];
				}
				mvpeers.clear();
				return 0;
			}

			virtual int WorkingTask()
			{
				miniutil::auto_lock lk(&mtx);
				int ret = 0;
				if(mlistensoc != NULL && mss.is_incoming(mlistensoc))
				{
					sockaddr_in addr;
					int addrlen = sizeof(sockaddr);

					SOCKET acceptsoc = mss.accept(mlistensoc,(sockaddr*)&addr, &addrlen);
					//std::cout<<"some one comming..."<<inet_ntoa(addr.sin_addr)<<std::endl;
                    std::cout<<"some one comming..."<<miniutil::socketcmn::ip_i2s(addr)<<std::endl;
					
					TN* newpeer = new TN(&mss, miniutil::soaddr(&addr), acceptsoc);
					mvpeers.push_back(newpeer);
					mss.add_tcp_socket(acceptsoc,miniutil::multinet::EVT_WRITE_READY|miniutil::multinet::EVT_READ_READY);
				}
				typename std::vector<TN*>::iterator iter_vt;
				for(iter_vt = mvpeers.begin(); iter_vt != mvpeers.end();)
				{
					ret = (*iter_vt)->working();
					if((*iter_vt)->GetNetStus() == MultinetPeer::STUS_CONN_FAIL ||
						(*iter_vt)->GetNetStus() == MultinetPeer::STUS_CONN_BROKE)
					{
						delete (*iter_vt);
						iter_vt = mvpeers.erase(iter_vt);
					}
					else
						iter_vt ++;
				}
				return 0;
			}
		protected:
			SOCKET mlistensoc;
			std::vector<TN*> mvpeers;
			unsigned short mport;
			miniutil::multinet::SocketMulplexService_Select mss;
			miniutil::mutex mtx;
	};
	
} }	

#endif
